#include "Registro.h"
#include "funciones.h"
#include <list>

namespace Toolkit
{

Registro::Registro(const TipoSerializacion tSerializacion) :
    Componente(tSerializacion)
{
    this->dato = NULL;
}

Registro::~Registro()
{
    if (this->dato != NULL) {
        delete dato;
    }
}

bool Registro::operator <(const Clave & clave) const
{
    return !(clave < (*dato) || clave == (*dato));
}

bool Registro::operator ==(const Clave & clave) const
{
    return clave == (*dato);
}

void Registro::setDato(const Dato &dato)
{
    if (this->dato != NULL) {
        delete this->dato;
    }

    this->dato = dato.clonar();
}

Dato* Registro::clonarDato() const
{
    if (this->tieneDato()) {
        return this->dato->clonar();
    }
    else {
        return NULL;
    }
}

void Registro::serializar(stringstream& s) const
{
    stringstream ssDato;

    if (tieneDato()) {
        this->dato->serializar(ssDato);
    }

    agregarTamanoASerializacionComp(ssDato, tSerializacion);

    char tipo = this->getTipo();
    s.write((char*) &tipo, sizeof(char));
    s.write(ssDato.str().c_str(), ssDato.str().size());
}

void Registro::hidratar(stringstream& s, const Dato &dato)
{
    char tipo = 0;
    int tamano = 0;
    char *bufferDatos;

    s.read((char *) &tipo, sizeof(char));

    if (getTipo() == tipo) {
        hidratacionDigito(s, tSerializacion, tamano);

        bufferDatos = new char[tamano];
        s.read(bufferDatos, tamano);

        stringstream ssDato;
        ssDato.write(bufferDatos, tamano);

        if (this->dato != NULL) {
            delete this->dato;
            this->dato = NULL;
        }

        this->setDato(dato);
        this->dato->hidratar(ssDato);

        delete[] bufferDatos;
    }

}

void Registro::hidratarDato(Dato &dato)
{
    stringstream serializacion;

    if (tieneDato()) {
        this->dato->serializar(serializacion);
        dato.hidratar(serializacion);
    }

}

char Registro::getTipo() const
{
    return 'R';
}

bool Registro::tieneDato() const
{
    return (this->dato != NULL);
}

Componente *Registro::clonar() const
{
    Registro *nuevo = new Registro(tSerializacion);

    if (this->tieneDato()) {
        nuevo->setDato(*(this->dato));
    }

    return nuevo;
}

list<Clave*> Registro::getClaves(const Clave &claveMolde) const
{
    list<Clave*> listaClave;

    if (this->dato != NULL) {
        Clave* clave = claveMolde.crearDesdeDato(*this->dato);
        listaClave.push_back(clave);
    }

    return listaClave;
}

}
